home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 December / CHIPNET Aralık 1997.iso / linux / redhat / misc / src / install / device~1.ewt < prev    next >
Encoding:
Text File  |  1997-08-11  |  21.8 KB  |  899 lines

  1. #include <alloca.h>
  2. #include <ctype.h>
  3. #include <fcntl.h>
  4. #include <newt.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/stat.h>
  8. #include <sys/sysmacros.h>
  9. #include <sys/types.h>
  10. #include <unistd.h>
  11.  
  12. #include "devices.h"
  13. #include "install.h"
  14. #include "log.h"
  15. #include "net.h"
  16. #include "perror.h"
  17. #include "run.h"
  18. #include "scsi.h"
  19. #include "windows.h"
  20.  
  21. #define MODULES_PATH "/modules/"
  22.  
  23. struct devnum {
  24.     char * name;
  25.     short major, minor;
  26. };
  27.  
  28. const static struct devnum devices[] = {
  29.     { "aztcd",        29,    0 },
  30.     { "cdu31a",        15,    0 },
  31.     { "cdu535",        24,    0 },
  32.     { "cm206cd",    32,    0 },
  33.     { "fd0",         2,    0 },
  34.     { "fd1",        2,    1 },
  35.     { "gscd",        16,    0 },
  36.     { "mcd",        23,    0 },
  37.     { "optcd",        17,    0 },
  38.     { "sbpcd",        25,    0 },
  39.     { "scd0",        11,    0 },
  40.     { "scd1",        11,    1 },
  41.     { "sjcd",        18,    0 },
  42. };
  43.  
  44. const int numDevices = sizeof(devices) / sizeof(struct devnum);
  45.  
  46. struct moduleOptions {
  47.     char * arg;
  48.     char * desc;
  49.     char * defaults;
  50. } ;
  51.  
  52. const struct moduleOptions neOptions[] = {
  53.    { "io", "Base IO port:", "0x300:0x280:0x320:0x340:0x360" },
  54.    { "irq", "IRQ level:", NULL },
  55.    { NULL, NULL, NULL }
  56. } ;
  57.  
  58. const struct moduleOptions de4x5Options[] = {
  59.    { "io", "Base IO port:", "0x0b" },
  60.    { NULL, NULL, NULL }
  61. } ;
  62.  
  63. const struct moduleOptions cdu31aOptions[] = {
  64.    { "cdu31a", "IO base, IRQ, PAS?:", "" },
  65.    { NULL, NULL, NULL }
  66. } ;
  67.  
  68. const struct moduleOptions cm206Options[] = {
  69.    { "cm206", "IO base, IRQ:", "" },
  70.    { NULL, NULL, NULL }
  71. } ;
  72.  
  73. const struct moduleOptions mcdOptions[] = {
  74.    { "mcd", "IO base address:", "" },
  75.    { NULL, NULL, NULL }
  76. } ;
  77.  
  78. const struct moduleOptions optcdOptions[] = {
  79.    { "optcd", "IO base address:", "" },
  80.    { NULL, NULL, NULL }
  81. } ;
  82.  
  83. const struct moduleOptions sbpcdOptions[] = {
  84.    { "sbpcd", "IO base, IRQ, label:", "" },
  85.    { NULL, NULL, NULL }
  86. } ;
  87.  
  88. #define MODULE_AUTOPROBE    (1 << 0)
  89. #define MODULE_FAKEAUTOPROBE    (1 << 1)
  90.  
  91. struct moduleInfo {
  92.     char * name;
  93.     int shouldAutoprobe;
  94.     const struct moduleOptions * options;
  95.     int flags;
  96.     char * defaultOptions;
  97. } ;
  98.  
  99. /* keep this alphabetical! */
  100. struct moduleInfo modules[] = { 
  101.     { "8390", 1, NULL, 0, NULL },
  102.     { "cdu31a", 0, cdu31aOptions, 0, NULL },
  103.     { "cm206", 0, cm206Options, 0, NULL },
  104.     { "de4x5", 1, de4x5Options, MODULE_AUTOPROBE, "io=0" },
  105.     { "ds", 1, NULL, 0, NULL },
  106.     { "loop", 1, NULL, 0, NULL },
  107.     { "mcd", 0, mcdOptions, 0, NULL },
  108.     { "ne", 0, neOptions, MODULE_FAKEAUTOPROBE, "io=0x300" },
  109.     { "optcd", 0, optcdOptions, 0, NULL },
  110.     { "pcmcia_core", 1, NULL, 0, NULL },
  111.     { "sbpcd", 1, sbpcdOptions, 0, NULL },
  112.     { NULL, 0, NULL, 0, NULL }                /* sentinel */
  113. } ;
  114.  
  115. struct driver {
  116.     char * name;
  117.     char * modules;
  118.     int isLoaded;
  119.     driverOkayFn okay;
  120.     enum driverTypes type;
  121. };
  122.  
  123. static int checkEthernetDev(struct driver * dev);
  124. static int checkSCSIDev(struct driver * dev);
  125.  
  126. static struct driver drivers[] = {
  127.     { "3com 3c509", "3c509", 0, checkEthernetDev, 
  128.         DRIVER_ETHERNET },
  129.     { "3com 3c59x (Vortex)", "3c59x", 0, checkEthernetDev,
  130.         DRIVER_ETHERNET },
  131.     { "3com 3c501", "3c501", 0, checkEthernetDev, 
  132.         DRIVER_ETHERNET },
  133.     { "3com 3c503", "8390:3c503", 0, checkEthernetDev, 
  134.         DRIVER_ETHERNET },
  135.     { "Apricot 82596", "apricot", 0, checkEthernetDev, 
  136.         DRIVER_ETHERNET },
  137.     { "Cabletron E2100", "8390:e2100", 0, checkEthernetDev, 
  138.         DRIVER_ETHERNET },
  139.     { "Digital 425,434,435,450,500", "de4x5", 0, checkEthernetDev, 
  140.         DRIVER_ETHERNET },
  141.     { "Digital DEPCA and EtherWORKS", "depca", 0, checkEthernetDev, 
  142.         DRIVER_ETHERNET },
  143.     { "Digital EtherWORKS 3", "ewrk3", 0, checkEthernetDev, 
  144.         DRIVER_ETHERNET },
  145.     { "Digital 21040 (Tulip)", "tulip", 0, checkEthernetDev, 
  146.         DRIVER_ETHERNET },
  147.     { "D-Link DE-600 pocket adapter", "de600", 0, checkEthernetDev, 
  148.         DRIVER_ETHERNET },
  149.     { "D-Link DE-620 pocket adapter", "de620", 0, checkEthernetDev, 
  150.         DRIVER_ETHERNET },
  151.     { "HP10/100VG any LAN ", "8390:hp", 0, checkEthernetDev, 
  152.         DRIVER_ETHERNET },
  153.     { "HP LAN", "hp", 0, checkEthernetDev, 
  154.         DRIVER_ETHERNET },
  155.     { "HP PCLAN/plus", "8390:hp-plus", 0, checkEthernetDev, 
  156.         DRIVER_ETHERNET },
  157.     { "Intel EtherExpress", "eexpress", 0, checkEthernetDev, 
  158.         DRIVER_ETHERNET },
  159.     { "NE2000 and compatible", "8390:ne", 0, checkEthernetDev, 
  160.         DRIVER_ETHERNET },
  161.     { "SMC 9000 series", "smc9194", 0, checkEthernetDev, 
  162.         DRIVER_ETHERNET },
  163.     { "SMC Ultra ethernet", "8390:smc-ultra", 0, checkEthernetDev, 
  164.         DRIVER_ETHERNET },
  165.     { "WD8003, WD8013 and compatible", "8390:wd", 0, checkEthernetDev,
  166.         DRIVER_ETHERNET },
  167.  
  168.     { "Adaptec 152x", "aha152x", 0, checkSCSIDev,
  169.         DRIVER_SCSI },
  170.     { "Adaptec 1542", "aha1542", 0, checkSCSIDev,
  171.         DRIVER_SCSI },
  172.     { "Adaptec 1740", "aha1740", 0, checkSCSIDev,
  173.         DRIVER_SCSI },
  174.     { "Adaptec 2740, 2840, 2940", "aic7xxx", 0, checkSCSIDev,
  175.         DRIVER_SCSI },
  176.     { "AdvanSys Adapters", "advansys", 0, checkSCSIDev,
  177.         DRIVER_SCSI },
  178.     { "Always IN2000", "in2000", 0, checkSCSIDev,
  179.         DRIVER_SCSI },
  180.     { "Buslogic Adapters", "BusLogic", 0, checkSCSIDev,
  181.         DRIVER_SCSI },
  182.     { "DTC 3180/3280", "dtc", 0, checkSCSIDev,
  183.         DRIVER_SCSI },
  184.     { "EATA DMA Adapters", "eata_dma", 0, checkSCSIDev,
  185.         DRIVER_SCSI },
  186.     { "EATA PIO Adapters)", "eata_pio", 0, checkSCSIDev,
  187.         DRIVER_SCSI },
  188.     { "Future Domain TMC-885, TMC-950", "seagate", 0, checkSCSIDev,
  189.         DRIVER_SCSI },
  190.     { "Future Domain TMC-16x0", "fdomain", 0, checkSCSIDev,
  191.         DRIVER_SCSI },
  192.     { "Iomega PPA3 (parallel port Zip)", "ppa", 0, checkSCSIDev,
  193.         DRIVER_SCSI },
  194.     { "NCR 5380", "g_NCR5380", 0, checkSCSIDev,
  195.         DRIVER_SCSI },
  196.     { "NCR 53c406a", "NCR53c406a", 0, checkSCSIDev,
  197.         DRIVER_SCSI },
  198.     { "NCR 53C810/53C820 PCI", "53c7,8xx", 0, checkSCSIDev,
  199.         DRIVER_SCSI },
  200.     { "Pro Audio Spectrum/Studio 16", "pas16", 0, checkSCSIDev,
  201.         DRIVER_SCSI },
  202.     { "Qlogic FAS", "qlogicfas", 0, checkSCSIDev,
  203.         DRIVER_SCSI },
  204.     { "Qlogic ISP", "qlogicisp", 0, checkSCSIDev,
  205.         DRIVER_SCSI },
  206.     { "Seagate ST01/02", "seagate", 0, checkSCSIDev,
  207.         DRIVER_SCSI },
  208.     { "Trantor T128/T128F/T228", "seagate", 0, checkSCSIDev,
  209.         DRIVER_SCSI },
  210.     { "UltraStor 14F/34F", "u14-34f", 0, checkSCSIDev,
  211.         DRIVER_SCSI },
  212.     { "UltraStor 14F/24F/34F", "ultrastor", 0, checkSCSIDev,
  213.         DRIVER_SCSI },
  214.     { "Western Digital wd7000", "wd7000", 0, checkSCSIDev,
  215.         DRIVER_SCSI },
  216.  
  217.     { "PCMCIA core support", "pcmcia_core", 0, NULL,
  218.         DRIVER_PCMCIA },
  219.     { "PCMCIA card support", "ds", 0, NULL,
  220.         DRIVER_PCMCIA },
  221.     { "PCMCIA i82365 controller", "i82365", 0, NULL,
  222.         DRIVER_PCMCIA },
  223.     { "PCMCIA tcic controller", "tcic", 0, NULL,
  224.         DRIVER_PCMCIA },
  225.  
  226.     { "Aztech CD", "aztcd", 0, NULL,
  227.         DRIVER_CDROM },
  228.     { "Goldstar R420", "gscd", 0, NULL,
  229.         DRIVER_CDROM },
  230.     { "Mitsumi", "mcd", 0, NULL,
  231.         DRIVER_CDROM },
  232.     { "Optics Storage 8000", "optcd", 0, NULL,
  233.         DRIVER_CDROM },
  234.     { "Phillips CM206/CM260", "cm206", 0, NULL,
  235.         DRIVER_CDROM },
  236.     { "Sanyo", "sjcd", 0, NULL, 
  237.         DRIVER_CDROM },
  238.     { "Sony CDU-31A", "cdu31a", 0, NULL, 
  239.         DRIVER_CDROM },
  240.     { "Sony CDU-5xx", "sonycd535", 0, NULL, 
  241.         DRIVER_CDROM },
  242.     { "SoundBlaster/Panasonic", "sbpcd", 0, NULL, 
  243.         DRIVER_CDROM },
  244.  
  245.     { "Loopback device", "loop", 0, NULL, DRIVER_OTHER },
  246.  
  247.     { NULL, NULL, 0, NULL, DRIVER_OTHER }, /* sentinel */
  248. };
  249.  
  250. static const int numDrivers = sizeof(drivers) / sizeof(struct driver);
  251.  
  252. static int loadDeviceModule(struct driver * driver, 
  253.                 struct driversLoaded ** drlist);
  254. static int getOptions(const char * name, int * argcp, char *** argvp);
  255. static struct driversLoaded * allocDL(struct driversLoaded ** drlist);
  256.  
  257. int devMakeInode(char * name, char * path) {
  258.     int i;
  259.     int major, minor;
  260.  
  261.     if (name[0] == 's' && name[1] == 'd') {
  262.     major = 8;
  263.     minor = (name[2] - 'a') << 4;
  264.     if (name[3] && name[4]) 
  265.        minor += 10 + (name[4] - '0');
  266.     else if (name[3])
  267.        minor += (name[3] - '0');
  268.     } else if (name[0] == 'h' && name[1] == 'd') {
  269.     if (name[2] == 'a') 
  270.         major = 3, minor = 0;
  271.     else if (name[2] == 'b')
  272.         major = 3, minor = 64;
  273.     else if (name[2] == 'c')
  274.         major = 22, minor = 0;
  275.     else if (name[2] == 'd')
  276.         major = 22, minor = 64;
  277.     else if (name[2] == 'e')
  278.         major = 33, minor = 0;
  279.     else if (name[2] == 'f')
  280.         major = 33, minor = 64;
  281.     else if (name[2] == 'g')
  282.         major = 34, minor = 0;
  283.     else if (name[2] == 'h')
  284.         major = 34, minor = 64;
  285.     else
  286.         return INST_ERROR;
  287.  
  288.     if (name[3] && name[4]) 
  289.        minor += 10 + (name[4] - '0');
  290.     else if (name[3])
  291.        minor += (name[3] - '0');
  292.     } else if (!strncmp(name, "ram", 3)) {
  293.     major = 1;
  294.     minor = 1;
  295.     if (name[3])
  296.         minor += name[3] - '1';
  297.     } else {
  298.     for (i = 0; i < numDevices; i++) {
  299.         if (!strcmp(devices[i].name, name)) break;
  300.     }
  301.     if (i == numDevices) return INST_ERROR;
  302.     major = devices[i].major;
  303.     minor = devices[i].minor;
  304.     }
  305.  
  306.     logMessage("making device %s (%d, %d) as %s", name, major, minor, path);
  307.  
  308.     if (testing)
  309.     messageWindow("mknod", "making device %s (%d, %d) as %s", 
  310.               name, major, minor, path);
  311.  
  312.     unlink(path);
  313.     if (mknod(path, S_IFBLK | 0600, makedev(major, minor))) {
  314.     messageWindow("Error", perrorstr("mknod() failed"));
  315.     return INST_ERROR;
  316.     }
  317.  
  318.     return 0;
  319. }
  320.  
  321. void devRemoveInode(char * path) {
  322.     logMessage("removing device file %s", path);
  323.     unlink(path);
  324. }
  325.  
  326. static int modulesPanel(enum driverTypes type, struct driver ** drvptr) {
  327.     int drCount = 0;
  328.     int i;
  329.     newtComponent label, f, listbox;
  330.     newtComponent okay, answer, cancel;
  331.  
  332.     for (i = 0; i < numDrivers; i++) {
  333.     if (drivers[i].type == type) drCount++;
  334.     }
  335.  
  336.     newtOpenWindow(17, 4, 45, 15, "Load module");
  337.  
  338.     f = newtForm(NULL, NULL, 0);
  339.     label = newtLabel(1, 1, "Which driver should I try?");
  340.     newtFormAddComponent(f, label);
  341.  
  342.     listbox = newtListbox(5, 3, 6, NEWT_LISTBOX_RETURNEXIT);
  343.  
  344.     drCount = 0;
  345.     for (i = 0; i < numDrivers; i++) {
  346.     if (drivers[i].type == type) {
  347.         newtListboxAddEntry(listbox, drivers[i].name, drivers + i);
  348.         drCount++;
  349.     }
  350.     }
  351.  
  352.     newtFormAddComponent(f, listbox);
  353.     okay = newtButton(8, 10, "Ok");
  354.     cancel = newtButton(28, 10, "Cancel");
  355.  
  356.     newtFormAddComponents(f, okay, cancel, NULL);
  357.  
  358.     answer = newtRunForm(f);
  359.  
  360.     if (answer == cancel) {
  361.     newtFormDestroy(f);
  362.     newtPopWindow();
  363.     return INST_CANCEL;
  364.     }
  365.  
  366.     *drvptr = newtListboxGetCurrent(listbox);
  367.  
  368.     newtFormDestroy(f);
  369.     newtPopWindow();
  370.  
  371.     return 0;
  372. }
  373.  
  374. int loadDeviceDriver(enum driverTypes type, struct driversLoaded ** drlist) {
  375.     struct driver * driver;
  376.     int rc;
  377.  
  378.     do {
  379.     rc = modulesPanel(type, &driver);
  380.     if (rc) return rc;
  381.  
  382.     rc = loadDeviceModule(driver, drlist);
  383.     if (rc == INST_ERROR) {
  384.         errorWindow("I can't find the device anywhere on your system!");
  385.     }
  386.     } while (rc);
  387.  
  388.     return 0;
  389. }
  390.  
  391. static int loadDeviceModule(struct driver * driver, 
  392.                 struct driversLoaded ** drlist) {
  393.     char * start, * chptr, ** modStack;
  394.     char moduleName[100];
  395.     int rc;
  396.     int nummods = 1;
  397.    
  398.     chptr = start = driver->modules;
  399.     while (*chptr) {
  400.     if (*chptr == ':') nummods++;
  401.     chptr++;
  402.     }
  403.  
  404.     modStack = alloca(sizeof(char *) * (nummods + 1));
  405.  
  406.     nummods = 0;
  407.     while (start && *start) {
  408.     chptr = strchr(start, ':');
  409.     if (chptr) {
  410.         strncpy(moduleName, start, chptr - start);
  411.         moduleName[chptr - start] = '\0';
  412.         start = chptr + 1;
  413.     } else {
  414.         strcpy(moduleName, start);
  415.         start = NULL;
  416.     }
  417.  
  418.     if ((rc = loadModule(moduleName, driver->type, drlist))) {
  419.         while (nummods) {
  420.         removeModule(modStack[--nummods]);
  421.         }
  422.         return rc;
  423.     }
  424.  
  425.     
  426.     modStack[nummods] = alloca(strlen(moduleName) + 1);
  427.     strcpy(modStack[nummods++], moduleName);
  428.     }
  429.  
  430.     if (driver->okay && !driver->okay(driver)) {
  431.     while (nummods) {
  432.         removeModule(modStack[--nummods]);
  433.     }
  434.     logMessage("device check function failed to find device");
  435.     return INST_ERROR;
  436.     }
  437.  
  438.     return 0;
  439. }
  440.  
  441. int removeModule(char * module) {
  442.     char * argv[] = { "/bin/rmmod", NULL, NULL };
  443.  
  444.     argv[1] = module;
  445.  
  446.     return runProgram(RUN_LOG, "/bin/rmmod", argv);
  447. }
  448.  
  449. int loadModule(char * modName, enum driverTypes type,
  450.            struct driversLoaded ** drlist) {
  451.     struct driversLoaded * dl;
  452.     char * objName;
  453.     char ** argv;
  454.     int argc;
  455.     int rc;
  456.     int clearWindow = 0;
  457.  
  458.     if (type == DRIVER_SCSI) {
  459.     winStatus(35, 3, "SCSI", "Scanning SCSI bus...");
  460.     clearWindow = 1;
  461.     }
  462.  
  463.     objName = alloca(strlen(modName) + 5 + strlen(MODULES_PATH));
  464.  
  465.     strcpy(objName, MODULES_PATH);
  466.     strcat(objName, modName);
  467.     strcat(objName, ".o");
  468.  
  469.     argc = 2;
  470.     argv = malloc((argc + 1) * sizeof(char *));
  471.     argv[0] = "/bin/insmod";
  472.     argv[1] = objName;
  473.     argv[2] = NULL;
  474.  
  475.     if ((rc = getOptions(modName, &argc, &argv))) {
  476.     free(argv);
  477.     if (clearWindow) newtPopWindow();
  478.     return rc;
  479.     } 
  480.  
  481.     if (runProgram(RUN_LOG, "/bin/insmod", argv)) {
  482.     free(argv);
  483.     logMessage("insmod failed!");
  484.     if (clearWindow) newtPopWindow();
  485.     return INST_ERROR;
  486.     }
  487.  
  488.     if (drlist) { 
  489.     dl = allocDL(drlist);
  490.  
  491.     dl->type = type;
  492.     dl->argv = argv;
  493.     dl->argc = argc;
  494.     dl->module = strdup(modName);
  495.     }
  496.  
  497.     if (clearWindow) newtPopWindow();
  498.  
  499.     return 0;
  500. }
  501.  
  502. static struct driversLoaded * allocDL(struct driversLoaded ** drlist) {
  503.     struct driversLoaded * new;
  504.  
  505.     if (*drlist == NULL) {
  506.     *drlist = malloc(sizeof(**drlist));
  507.     new = *drlist;
  508.     } else {
  509.     new = *drlist;
  510.     while (new->next) new = new->next;
  511.     new->next = malloc(sizeof(**drlist));
  512.     new = new->next;
  513.     }
  514.  
  515.     new->next = NULL;
  516.  
  517.     return new;
  518. }
  519.  
  520. #define OPTIONS_SPECIFY ((void *) 1)
  521. #define OPTIONS_DEFAULT ((void *) 2)
  522.  
  523. static int getOptions(const char * name, int * argcp, char *** argvp) {
  524.     newtComponent form, listbox, text, okay, answer, cancel;
  525.     char ** parameters = NULL;
  526.     char * miscParameters;
  527.     char buf[2000];
  528.     struct moduleInfo * mod;
  529.     void * choice;
  530.     int numOptions, col, miscRow, buttonRow, i;
  531.     const struct moduleOptions * option;
  532.     char * miscText;
  533.     char * chptr, * start;
  534.  
  535.     mod = modules;
  536.     while (mod->name) {
  537.     if (!strcmp(mod->name, name)) break;
  538.     mod++;
  539.     }
  540.     if (!mod->name) mod = NULL;
  541.     
  542.     if (mod && !mod->options) {
  543.     (*argcp)++;
  544.     (*argvp) = realloc(*argvp, (*argcp + 1) * sizeof(char *));
  545.     (*argvp)[(*argcp) - 1] = mod->defaultOptions;
  546.     (*argvp)[(*argcp)] = NULL;
  547.     if (!mod->defaultOptions)
  548.         (*argcp)--;
  549.     
  550.     return 0;
  551.     }
  552.  
  553.     if (!mod || mod->shouldAutoprobe) {
  554.     sprintf(buf, "In some cases, the %s driver needs to have extra "
  555.         "information to work properly, although it normally works "
  556.         "fine without. Would you like to specify extra options "
  557.         "for it or allow the driver to probe your machine for the "
  558.         "information it needs? Occasionally, probing will hang a "
  559.         "computer, but it should not cause any damage.", name);
  560.  
  561.     newtOpenWindow(10, 4, 60, 16, "Module Options");
  562.     listbox = newtListbox(20, 9, 0, NEWT_LISTBOX_RETURNEXIT);
  563.     newtListboxAddEntry(listbox, "Autoprobe", OPTIONS_DEFAULT);
  564.     newtListboxAddEntry(listbox, "Specify options", OPTIONS_SPECIFY);
  565.     buttonRow = 12;
  566.     } else {
  567.     sprintf(buf, "In many cases, the %s driver needs to be provided with "
  568.         "extra information on your hardware. If you prefer, "
  569.         "some common values for those parameters will be tried. "
  570.         "This process can hang a machine, although it should "
  571.         "not cause any damage.", name);
  572.     newtOpenWindow(10, 5, 60, 14, "Module Options");
  573.     listbox = newtListbox(20, 7, 0, NEWT_LISTBOX_RETURNEXIT);
  574.     newtListboxAddEntry(listbox, "Specify options", OPTIONS_SPECIFY);
  575.     newtListboxAddEntry(listbox, "Autoprobe", OPTIONS_DEFAULT);
  576.     buttonRow = 10;
  577.     }
  578.  
  579.     text = newtTextbox(1, 1, 55, 7, NEWT_TEXTBOX_WRAP);
  580.     newtTextboxSetText(text, buf);
  581.  
  582.     okay = newtButton(13, buttonRow, "Ok");
  583.     cancel = newtButton(39, buttonRow, "Cancel");
  584.  
  585.     form = newtForm(NULL, NULL, 0);
  586.     newtFormAddComponents(form, text, listbox, okay, cancel, NULL);
  587.  
  588.     answer = newtRunForm(form);
  589.     newtPopWindow();
  590.  
  591.     choice = newtListboxGetCurrent(listbox);
  592.     newtFormDestroy(form);
  593.  
  594.     if (answer == cancel) {
  595.     return INST_CANCEL;
  596.     }
  597.  
  598.     if (choice == OPTIONS_DEFAULT) {
  599.     (*argcp)++;
  600.     (*argvp) = realloc(*argvp, (*argcp + 1) * sizeof(char *));
  601.     if (mod)
  602.         (*argvp)[(*argcp) - 1] = mod->defaultOptions;
  603.     (*argvp)[(*argcp)] = NULL;
  604.     if (!mod || !mod->defaultOptions)
  605.         (*argcp)--;
  606.     
  607.     return 0;
  608.     }
  609.  
  610.     form = newtForm(NULL, NULL, 0);
  611.     newtFormAddComponent(form, newtLabel(1, 1, "Module options:"));
  612.  
  613.     numOptions = 0;
  614.     col = 0;
  615.     if (mod) {
  616.     option = mod->options;
  617.     while (option->arg) {
  618.         newtFormAddComponent(form, newtLabel(3, 3 + numOptions, 
  619.                  option->desc));
  620.         if (strlen(option->desc) > col) col = strlen(option->desc);
  621.         numOptions++;
  622.         option++;
  623.     }
  624.     miscText = "Miscellaneous options:";
  625.     } else {
  626.     miscText = "Module options:";
  627.     }
  628.  
  629.     if (numOptions) 
  630.     miscRow = 4 + numOptions; 
  631.     else
  632.     miscRow = 3;
  633.  
  634.     newtFormAddComponent(form, newtLabel(3, miscRow, "Miscellaneous options:"));
  635.  
  636.     if (22 > col) col = 22;
  637.  
  638.     if (numOptions) {
  639.     parameters = alloca(sizeof(*parameters) * numOptions);
  640.     numOptions = 0;
  641.     option = mod->options;
  642.     while (option->arg) {
  643.         sprintf(buf, "%s=", option->arg);
  644.         newtFormAddComponent(form, newtEntry(col + 5, 3 + numOptions, 
  645.                  buf, 20, parameters + numOptions, 
  646.                  NEWT_ENTRY_SCROLL));
  647.         numOptions++;
  648.         option++;
  649.     }
  650.     }
  651.  
  652.     newtFormAddComponent(form, newtEntry(col + 5, miscRow, "", 20,
  653.              &miscParameters, NEWT_ENTRY_SCROLL));
  654.  
  655.     newtOpenWindow((80 - (col + 30)) / 2, (25 - (miscRow + 6)) / 2, col + 30,
  656.             miscRow + 6, "Module Parameters");
  657.  
  658.     okay = newtButton((col + 10) / 3, miscRow + 2, "Ok");
  659.     cancel = newtButton(10 + 2 * ((col + 10) / 3), miscRow + 2, "Cancel");
  660.     newtFormAddComponents(form, okay, cancel, NULL);
  661.  
  662.     answer = newtRunForm(form);
  663.  
  664.     newtPopWindow();
  665.  
  666.     if (answer == cancel) {
  667.     newtFormDestroy(form);
  668.     return INST_CANCEL;
  669.     }
  670.  
  671.     if (mod) {
  672.     i = *argcp;
  673.     (*argcp) += numOptions;
  674.     (*argvp) = realloc(*argvp, (*argcp + 1) * sizeof(char *));
  675.     numOptions = 0;
  676.      
  677.     option = mod->options;
  678.     while (option->arg) {
  679.         sprintf(buf, "%s=", option->arg);
  680.         if (strcmp(parameters[numOptions], buf))
  681.         (*argvp)[i++] = strdup(parameters[numOptions]);
  682.         numOptions++, option++;
  683.     }
  684.     (*argcp) = i;
  685.     }
  686.  
  687.     chptr = miscParameters;
  688.     numOptions = 0;
  689.     while (*chptr) {
  690.     while (isspace(*chptr) && *chptr) chptr++;
  691.     if (!*chptr) continue;
  692.     
  693.     numOptions++;
  694.     while (!isspace(*chptr) && *chptr) chptr++;
  695.     }
  696.  
  697.     i = *argcp;
  698.     (*argcp) += numOptions;
  699.     (*argvp) = realloc(*argvp, (*argcp + 1) * sizeof(char *));
  700.     numOptions = 0;
  701.  
  702.     chptr = miscParameters;
  703.     numOptions = 0;
  704.     while (*chptr) {
  705.     while (isspace(*chptr) && *chptr) chptr++;
  706.     if (!*chptr) continue;
  707.     
  708.     start = chptr;
  709.     numOptions++;
  710.     while (!isspace(*chptr) && *chptr) chptr++;
  711.  
  712.     if (*chptr) {
  713.         *chptr = '\0';
  714.         (*argvp)[i++] = strdup(start);
  715.         *chptr = ' ';
  716.     } else
  717.         (*argvp)[i++] = strdup(start);
  718.     }
  719.     (*argcp) = i;
  720.     (*argvp)[*argcp] = NULL;
  721.  
  722.     newtFormDestroy(form);
  723.  
  724.     return 0;
  725. }
  726.  
  727. int readModuleConf(char * prefix, struct driversLoaded ** drlist) {
  728.     char buf[255];
  729.     FILE * f;
  730.     char * start, * end, * chptr;
  731.     struct driversLoaded * item = NULL;
  732.  
  733.     if (testing) return 0;
  734.  
  735.     strcpy(buf, prefix);
  736.     strcat(buf, "/conf.modules");
  737.  
  738.     f = fopen(buf, "r");
  739.     if (!f) {
  740.     return INST_ERROR;
  741.     }
  742.  
  743.     while (fgets(buf, sizeof(buf) - 1, f)) {
  744.      start = buf;
  745.     end = start + strlen(start) - 1;
  746.     *end = '\0';
  747.  
  748.     if (!strncmp(start, "alias ", 6)) {
  749.         start += 6;
  750.  
  751.         if (!strncmp(start, "eth", 3)) {
  752.         start += 5;
  753.  
  754.         item = allocDL(drlist);
  755.  
  756.         item->module = strdup(start);
  757.         item->argv = NULL;
  758.         item->argc = 0;
  759.         item->type = DRIVER_ETHERNET;
  760.         } else if (!strncmp(start, "scsi_hostadapter", 16)) {
  761.         start += 17;
  762.         while (isspace(*start) && *start) start++;
  763.         if (!*start) continue;
  764.  
  765.         item = allocDL(drlist);
  766.  
  767.         item->module = strdup(start);
  768.         item->argv = NULL;
  769.         item->argc = 0;
  770.         item->type = DRIVER_SCSI;
  771.         }
  772.     } else if (!strncmp(start, "options ", 8)) {
  773.         start += 8;
  774.  
  775.         chptr = start;
  776.         while (!isspace(*chptr) && *chptr) chptr++;
  777.         if (!*chptr) continue;
  778.         
  779.         *chptr = '\0';
  780.         
  781.         item = *drlist;
  782.         while (item && strcmp(item->module, start)) item = item->next; 
  783.  
  784.         if (!item) {
  785.         item = allocDL(drlist);
  786.         item->module = strdup(start);
  787.         item->argv = NULL;
  788.         item->argc = 0;
  789.         item->type = DRIVER_ETHERNET;
  790.         }
  791.  
  792.         item->argv = malloc(sizeof(char *) * 5);
  793.         item->argc = 3;
  794.         item->argv[2] = strdup(chptr + 1);
  795.     }
  796.     }
  797.  
  798.     fclose(f);
  799.  
  800.     return 0;
  801. }
  802.  
  803. int writeModuleConf(char * prefix, struct driversLoaded * dl) {
  804.     char buf[255];
  805.     FILE * f;
  806.     int i;
  807.  
  808.     if (testing) return 0;
  809.  
  810.     strcpy(buf, prefix);
  811.     strcat(buf, "/conf.modules");
  812.  
  813.     f = fopen(buf, "w");
  814.     if (!f) {
  815.     errorWindow("cannot create module config file: %s");
  816.     return INST_ERROR;
  817.     }
  818.  
  819.     while (dl) {
  820.     if (dl->type == DRIVER_ETHERNET) {
  821.         fprintf(f, "alias eth0 %s\n", dl->module);
  822.     }
  823.     else if (dl->type == DRIVER_SCSI) {
  824.         fprintf(f, "alias scsi_hostadapter %s\n", dl->module);
  825.     }
  826.  
  827.     if (dl->argc > 2) {
  828.         fprintf(f, "options %s", dl->module);
  829.         for (i = 2; i < dl->argc; i++) {
  830.         fprintf(f, " %s", dl->argv[i]);
  831.         }
  832.     
  833.         fprintf(f, "\n");
  834.     }
  835.  
  836.     dl = dl->next;
  837.     }
  838.  
  839.     fclose(f);
  840.  
  841.     return 0;
  842. }
  843.  
  844. static int checkSCSIDev(struct driver * dev) {
  845.     return scsiDeviceAvailable();
  846. }
  847.  
  848. static int checkEthernetDev(struct driver * dev) {
  849.     return netDeviceAvailable("eth0");
  850. }
  851.  
  852. /* This assumes only one of each driver type is loaded */
  853. int removeDeviceDriver(enum driverTypes type, struct driversLoaded ** drlist) {
  854.     char * buf, * chptr;
  855.     struct driversLoaded * dl, * head;
  856.     struct driver * dri;
  857.  
  858.     dl = *drlist;
  859.     while (dl && dl->type != type) {
  860.     dl = dl->next;
  861.     }
  862.     if (!dl) return 0;
  863.  
  864.     dri = drivers;
  865.     while (dri->name) {
  866.     if (!strcmp(dri->modules, dl->module)) break;
  867.     dri++;
  868.     }
  869.  
  870.     if (!dri->name) return 0;
  871.  
  872.     buf = alloca(strlen(dri->modules) + 1);
  873.     strcpy(buf, dri->modules);
  874.  
  875.     chptr = buf + strlen(buf) - 1;
  876.     while (chptr > buf) {
  877.     while (chptr > buf && *chptr != ':') chptr--;
  878.     if (*chptr == ':') {
  879.         chptr = '\0';
  880.         removeModule(chptr + 1);
  881.         chptr--;
  882.     }
  883.     }
  884.  
  885.     removeModule(buf);
  886.  
  887.     if (dl == *drlist) {
  888.     *drlist = dl->next;
  889.     free(dl);
  890.     } else if (dl) {
  891.     head = *drlist;
  892.     while (head->next != dl) head = head->next;
  893.     head->next = dl->next;
  894.     free(dl);
  895.     }
  896.  
  897.     return 0;
  898. }
  899.